home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvibook / libtex / gffont.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  22KB  |  944 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/gffont.c,v 2.9 89/09/02 17:16:17 chris Exp $";
  10. #endif
  11.  
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include "types.h"
  16. #include "error.h"
  17. #include "font.h"
  18. #include "gfcodes.h"
  19. #include "gfclass.h"
  20. #include "num.h"
  21.  
  22. /*
  23.  * GF font operations.
  24.  *
  25.  * GF files may be compact, but this code surely is not!
  26.  *
  27.  * TODO:
  28.  *    think about fonts with characters outside [0..255]
  29.  *    find some way to free gf body when done
  30.  */
  31. static int gf_read(), gf_getgly(), gf_rasterise();
  32. static void gf_freefont();
  33.  
  34. struct    fontops gfops =
  35.     { "gf", 0, 1.0, gf_read, gf_getgly, gf_rasterise, gf_freefont };
  36.  
  37. /*
  38.  * Local info.
  39.  */
  40.  
  41. /*
  42.  * A bounding box.  The names follow those in the GF documentation.
  43.  */
  44. struct bounds {
  45.     i32    min_m, max_m;    /* min and max `m' (colunm) values */
  46.     i32    min_n, max_n;    /* min and max `n' (row) values */
  47. };
  48.  
  49. /*
  50.  * char_loc is one `character locator' from a GF file, save for the
  51.  * `character residue', which we need not.
  52.  */
  53. struct char_loc {
  54.     i32    cl_dx;        /* x escapement (scaled pixels) */
  55.     i32    cl_dy;        /* y escapement (scaled pixels) */
  56.     i32    cl_w;        /* TFM width */
  57.     i32    cl_p;        /* pointer to BOC (or specials) */
  58. };
  59.  
  60. /*
  61.  * GF details include:
  62.  *  ->    the main body of the GF file (all bytes save pre- and post-amble);
  63.  *  ->    global box boundaries;
  64.  * and    character locators, addressed by `character residue'.  Empty
  65.  *    slots are indicated by a -1 `pointer'.
  66.  */
  67. struct gf_details {
  68.     char    *gd_body;        /* GF body */
  69.     char    *gd_base;        /* == gd_body - preamble_size */
  70.     struct    bounds gd_gb;        /* global boundaries */
  71.     struct    char_loc gd_cl[256];    /* character locators */
  72. };
  73.  
  74. /*
  75.  * Get the gf_details from font f.
  76.  */
  77. #define    ftogd(f) ((struct gf_details *)(f)->f_details)
  78.  
  79. extern    int errno;
  80. char    *malloc(), *copyit();
  81.  
  82. /*
  83.  * This code mimicks findpost.c.
  84.  */
  85. #define    POSTSIZE    512
  86.  
  87. /*
  88.  * Find the GF postamble.  Store the offsets of the POST and POSTPOST
  89.  * opcodes through postp and postpostp.
  90.  */
  91. static int
  92. findGFpostamble(fd, postp, postpostp)
  93.     int fd;
  94.     long *postp, *postpostp;
  95.  
  96. {
  97.     register long offset;
  98.     register char *p;
  99.     register int i;
  100.     register i32 n;
  101.     char postbuf[POSTSIZE];
  102.  
  103.     offset = lseek(fd, 0L, 2);
  104.     do {
  105.         
  106.         if ((offset -= POSTSIZE) < 0L)
  107.             offset = 0L;
  108.         (void) lseek(fd, offset, 0);
  109.         i = read(fd, postbuf, POSTSIZE);
  110.         if (i <= 0)
  111.             break;
  112.         for (p = postbuf + i; --i >= 0;)
  113.             if (UnSign8(*--p) != GF_FILLER)
  114.                 goto found_something;
  115.     } while (offset);
  116.     return (-1);        /* ran out of filler */
  117.  
  118. found_something:
  119.     if (UnSign8(*p) != GF_ID)
  120.         return (-1);    /* not a GF file */
  121.     offset += i;        /* this is the offset of *p */
  122.     *postpostp = offset - 5;/* POSTPOST should be here */
  123.     /* we need 4 bytes for the pointer */
  124.     if (i >= 4)
  125.         p -= 4;
  126.     else {
  127.         offset -= 4;
  128.         if (offset < 0L)
  129.             return (-1);    /* tsk */
  130.         (void) lseek(fd, offset, 0);
  131.         if (read(fd, p = postbuf, 4) != 4)
  132.             return (-1);
  133.     }
  134.     /*
  135.      * p now points to the postamble pointer.  Get it and
  136.      * seek to the postamble, also saving the offset.
  137.      */
  138.     pGetLong(p, n);
  139.     *postp = offset = n;
  140.     (void) lseek(fd, offset, 0);
  141.     return (0);        /* made it */
  142. }
  143.  
  144. /*
  145.  * Read a GF file.
  146.  */
  147. static int
  148. gf_read(f, fd)
  149.     register struct font *f;
  150.     int fd;
  151. {
  152.     register struct gf_details *gd;
  153.     register char *p;
  154.     register struct char_loc *cl;
  155.     register int i;
  156.     int presize, postsize, bodysize, firstc, lastc;
  157.     char *postamble;
  158.     long postaddr, postpostaddr;
  159.     i32 lasteoc;
  160.     char *problem = NULL;
  161.     struct stat st;
  162.     char b[4];
  163.     int saverr;
  164.  
  165.     gd = NULL;        /* prepare for failure */
  166.     postamble = NULL;
  167.  
  168.     /*
  169.      * The file had best be at least 50 bytes long.  A
  170.      * `completely empty' GF file might consist of a PRE, a GF_ID,
  171.      * no comment (one zero byte), then: POST, pointer to last
  172.      * EOC, design size, checksum, hppp, vppp, min_m, max_m,
  173.      * min_n, max_n, POSTPOST, pointer to POST, GF_ID, and four
  174.      * FILLERs.
  175.      */
  176.     (void) fstat(fd, &st);
  177.     if (st.st_size < 50) {    /* too small to be a GF file */
  178.         problem = "file is too short";
  179.         goto fail;
  180.     }
  181.  
  182.     /*
  183.      * Read the very beginning and pick up the preamble size.
  184.      */
  185.     if (read(fd, b, 4) != 4)
  186.         goto fail;
  187.     if (UnSign8(b[0]) != GF_PRE) {
  188.         problem = "file does not begin with PRE";
  189.         goto fail;
  190.     }
  191.     i = UnSign8(b[1]);
  192.     if (i != GF_ID)
  193.         error(0, 0, "Warning: strange GF id (%d) in \"%s\"", i,
  194.             f->f_path);
  195.     presize = 3 + UnSign8(b[2]);
  196.  
  197.     /*
  198.      * Find the postamble, allocate space, and read it in.
  199.      */
  200.     if (findGFpostamble(fd, &postaddr, &postpostaddr)) {
  201.         problem = "cannot find postamble";
  202.         goto fail;
  203.     }
  204.     postsize = postpostaddr - postaddr + 1;
  205.     if ((p = malloc(postsize)) == NULL)
  206.         goto fail;
  207.     if (read(fd, p, postsize) != postsize)
  208.         goto fail;
  209.     postamble = p;
  210.     
  211.     /*
  212.      * Make sure we found it.
  213.      */
  214.     if (pgetbyte(p) != GF_POST) {
  215.         problem = "no GF_POST at postamble";
  216.         goto fail;
  217.     }
  218.     if (UnSign8(postamble[postsize - 1]) != GF_POSTPOST) {
  219.         problem = "no GF_POSTPOST after postamble";
  220.         goto fail;
  221.     }
  222.  
  223.     /*
  224.      * Looks okay.  Allocate detail space and poke through the postamble.
  225.      */
  226.     if ((gd = (struct gf_details *) malloc(sizeof (*gd))) == NULL)
  227.         goto fail;
  228.     gd->gd_body = NULL;
  229.  
  230.     pGetLong(p, lasteoc);    /* actually one past last EOC */
  231.     pGetLong(p, f->f_design_size);
  232.     pGetLong(p, f->f_checksum);
  233.     pGetLong(p, f->f_hppp);
  234.     pGetLong(p, f->f_vppp);
  235.  
  236.     pGetLong(p, gd->gd_gb.min_m);
  237.     pGetLong(p, gd->gd_gb.max_m);
  238.     pGetLong(p, gd->gd_gb.min_n);
  239.     pGetLong(p, gd->gd_gb.max_n);
  240.  
  241.     /*
  242.      * Zap all the character locators, then read those that are
  243.      * defined in the postamble.  Remember the first and last
  244.      * characters so that we know which glyphs are defined.  Lastc
  245.      * is actually the last-plus-one'th character.
  246.      */
  247.     for (cl = gd->gd_cl, i = 256; --i >= 0; cl++)
  248.         cl->cl_p = -1;
  249.     firstc = 256;
  250.     lastc = 0;
  251.     for (;;) {
  252.         i32 dx, dy;
  253.  
  254.         switch (pgetbyte(p)) {
  255.  
  256.         case GF_CHAR_LOC:
  257.             i = pgetbyte(p);
  258.             pGetLong(p, dx);
  259.             pGetLong(p, dy);
  260.             goto merge;
  261.  
  262.         case GF_CHAR_LOC0:
  263.             i = pgetbyte(p);
  264.             dx = ((i32) pgetbyte(p)) << 16;
  265.             dy = 0;
  266. merge:
  267.             if (i < firstc)
  268.                 firstc = i;
  269.             if (i >= lastc)
  270.                 lastc = i + 1;
  271.             cl = &gd->gd_cl[i];
  272.             cl->cl_dx = dx;
  273.             cl->cl_dy = dy;
  274.             pGetLong(p, cl->cl_w);
  275.             pGetLong(p, cl->cl_p);
  276.             break;
  277.  
  278.         case GF_POSTPOST:
  279.             goto done;
  280.  
  281.         default:
  282.             error(0, 0, "I do not understand %d here",
  283.                 UnSign8(p[-1]));
  284.             problem = "unexpected opcode in postamble";
  285.             goto fail;
  286.         }
  287.     }
  288. done:
  289.     free(postamble);
  290.     postamble = NULL;    /* all done with it */
  291.  
  292.     /*
  293.      * Alas, we need the instructions whether or not we need
  294.      * the rasters, since the raster bounding box information
  295.      * can only be properly determined by converting the rasters.
  296.      * Compute the size of the main body of the GF file, then
  297.      * read it in.
  298.      */
  299.     bodysize = lasteoc - presize;
  300.     if ((gd->gd_body = malloc(bodysize + 1)) == NULL)
  301.         goto fail;
  302.     (void) lseek(fd, (long) presize, 0);
  303.     if (read(fd, gd->gd_body, bodysize) != bodysize)
  304.         goto fail;
  305.     /*
  306.      * The next byte might be a special, so we just
  307.      * arbitrarily stuff in a POST.
  308.      */
  309.     gd->gd_body[bodysize] = GF_POST;
  310.     gd->gd_base = gd->gd_body - presize;
  311.  
  312.     f->f_details = (char *)gd;
  313.     if (FontHasGlyphs(f, firstc, lastc))
  314.         goto fail2;
  315.     (void) close(fd);
  316.     return (0);
  317.  
  318. fail:
  319.     if (problem == NULL)
  320.         error(0, errno, "trouble reading \"%s\"", f->f_path);
  321.     else {
  322.         error(0, 0, "%s", problem);
  323.         error(0, 0, "(are you sure \"%s\" is a GF file?)", f->f_path);
  324.     }
  325.     errno = 0;
  326. fail2:
  327.     saverr = errno;
  328.     if (postamble != NULL)
  329.         free(postamble);
  330.     if (gd != NULL) {
  331.         if (gd->gd_body != NULL)
  332.             free(gd->gd_body);
  333.         free((char *) gd);
  334.     }
  335.     (void) close(fd);
  336.     errno = saverr;
  337.     return (-1);
  338. }
  339.  
  340. /*
  341.  * Some global variables, used while building rasters.  (These are
  342.  * referenced also in copyit(), so must be global.  Fortunately, no
  343.  * one yet requires the font routines to be re-entrant.)
  344.  */
  345. static char *buildraster;    /* raster being built */
  346. static int buildsize;        /* size of buildraster (bytes) */
  347.  
  348. static struct bounds tempb;    /* bounds used during buildraster */
  349. static struct bounds ob;    /* observed bounds */
  350.  
  351. /*
  352.  * Bit tables: `left' and `right' bits.  lbits[b] has all the bits
  353.  * that are to the left of bit b set; rbits[b] has all the bits
  354.  * that are to the right of bit b set, as well as bit b itself.
  355.  */
  356. static char lbits[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  357. static char rbits[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
  358.  
  359. /*
  360.  * The magic address `nullraster' is known in getgly() as a valid
  361.  * but empty raster, and changed there to NULL.  A NULL return from
  362.  * drawchar indicates failure; we need something to distinguish the
  363.  * empty raster.
  364.  */
  365. static char nullraster[1];
  366.  
  367. /*
  368.  * `Inline functions':
  369.  *  ->    convert a bit number to a byte number (round down);
  370.  *  ->    convert a number of bits to a number of bytes (round up);
  371.  * and    convert a bit to a bit index.
  372.  */
  373. #define btoby(b) ((b) >> 3)
  374. #define    btonb(b) (((b) + 7) >> 3)
  375. #define    btobi(b) ((b) & 7)
  376.  
  377. /*
  378.  * Helper function for getgly: build the raster, and compute its
  379.  * minimal bounding box.  Called with `p' pointing past the backpointer
  380.  * field of the BOC command (i.e., at min_m or del_m).  `abbrev' is true
  381.  * iff this was a BOC1.  `globalb' are the global bounds from the GF file,
  382.  * whose name is pointed to by gfname.
  383.  */
  384. static char *
  385. drawchar(p, abbrev, globalb, gfname)
  386.     register char *p;
  387.     int abbrev;
  388.     struct bounds globalb;
  389.     char *gfname;
  390. {
  391.     register i32 m;        /* m register (column) */
  392.     register char *colp;    /* pointer to byte corresponding to m */
  393.     register int c;        /* temporary */
  394.     register i32 i;        /* temporary */
  395.     register int black;    /* true when paint_switch==black */
  396.     register i32 n;        /* n register (row) */
  397.     int stride;        /* multiplier to convert linear to 2d array */
  398.     int wrotethisrow;    /* true iff we wrote in the current row */
  399.     char *virtrast;        /* virtual origin version of buildraster */
  400.     int mustcopy;        /* true if we must copy the built raster */
  401.     struct bounds gb;    /* bounds from the GF file */
  402.  
  403.     /* get the bounds */
  404.     if (abbrev) {
  405.         c = pgetbyte(p);/* del_m */
  406.         gb.min_m = (gb.max_m = pgetbyte(p)) - c;
  407.         c = pgetbyte(p);/* del_n */
  408.         gb.min_n = (gb.max_n = pgetbyte(p)) - c;
  409.     } else {
  410.         pGetLong(p, gb.min_m);
  411.         pGetLong(p, gb.max_m);
  412.         pGetLong(p, gb.min_n);
  413.         pGetLong(p, gb.max_n);
  414.     }
  415.  
  416.     /*
  417.      * Trim the GF bounds according to the global bounds.  We
  418.      * use the trimmed values to allocate the build space.
  419.      */
  420.     tempb = gb;
  421. #define    GB_ADJ(field, cmp) \
  422.     if (tempb.field cmp globalb.field) \
  423.         tempb.field = globalb.field
  424.     GB_ADJ(min_m, <);
  425.     GB_ADJ(max_m, >);
  426.     GB_ADJ(min_n, <);
  427.     GB_ADJ(max_n, >);
  428. #undef GB_ADJ
  429.  
  430.     /*
  431.      * First check for completely empty characters---that is,
  432.      * those where min > max.  The space in cmtex10, for instance,
  433.      * could be a completely empty character, but for some reason
  434.      * METAFONT declares cmtex10 space as [0..0][0..0].
  435.      * Nonetheless, we will not assume that [0..-1][0..0] or
  436.      * the like are impossible.
  437.      */
  438.     if (tempb.min_m > tempb.max_m || tempb.min_n > tempb.max_n)
  439.         return (nullraster);
  440.  
  441.     /*
  442.      * Compute the distance between rows (the number of bytes per
  443.      * column), then make sure there is room in the build space
  444.      * for [min_n..max_n] of these, possibly by allocating a new raster.
  445.      */
  446.     stride = btonb(tempb.max_m - tempb.min_m + 1);
  447.     c = stride * (tempb.max_n - tempb.min_n + 1);
  448.     if (c > buildsize) {
  449.         if (buildraster != NULL)
  450.             free(buildraster);
  451.         if ((buildraster = malloc(c)) == NULL) {
  452.             buildsize = 0;
  453.             return (NULL);
  454.         }
  455.         buildsize = c;
  456.     }
  457.  
  458.     /*
  459.      * If we are using an old raster that is too big, remember to
  460.      * scrunch it down later.
  461.      */
  462.     mustcopy = buildsize > c;
  463.  
  464.     /* clear the raster to white */
  465.     bzero(buildraster, c);
  466.  
  467.     /*
  468.      * Make a virtual origin raster pointer.  The virtual origin is
  469.      * where raster[0][0] is, whether or not there is a raster[0][0].
  470.      * Normally, this would be
  471.      *    &buildraster[-gb.min_n * stride - btoby(gb.min_m)],
  472.      * but it is complicated by two things.  Firstly, we would like
  473.      * n==max_n to be the bottommost point in the raster (low
  474.      * addresses), and n==min_n to be the topmost (high addresses).
  475.      * In other words, we need to reflect the n (Y) values about
  476.      * the X axis: negate them.  Secondly, the raster we create
  477.      * must be `flush left'.  That is, somewhere along its rows,
  478.      * bit 0x80 must be set at the left edge of one of its columns.
  479.      * We need to subtract away the minimum bit index before
  480.      * calculating bit values.  This cannot really be done in
  481.      * advance, since we cannot address bits directly.
  482.      */
  483.     virtrast = &buildraster[gb.max_n * stride];
  484.  
  485.     /*
  486.      * Set up the bounds-trimming variables.  We could do this by
  487.      * simply setting the observed min point to a very large number,
  488.      * and the observed max point to a very small number, but this
  489.      * way we need not come up with extreme numbers (which might not
  490.      * be portable).
  491.      *
  492.      * If at least one pixel is blackened, the observed bounds will
  493.      * become the correct bounds in the code below, and we will have
  494.      * min<=max; but if no pixels are blackened, we arrange to have
  495.      * min>max, so we have to check for that again later.
  496.      *
  497.      * This would be `min = max + 1' and `max = min - 1', but for
  498.      * efficiency, the observed m bounds are kept offset by gb.min_m
  499.      * until we finish drawing the character.
  500.      */
  501.     ob.min_m = tempb.max_m + 1 - gb.min_m;
  502.     ob.max_m = tempb.min_m - 1 - gb.min_m;
  503.     ob.min_n = tempb.max_n + 1;
  504.     ob.max_n = tempb.min_n - 1;
  505.     wrotethisrow = 0;
  506.  
  507. #define FIX_N_BOUNDS() { \
  508.     if (wrotethisrow) { \
  509.         c = -n; /* recall that n is reflected about X axis */ \
  510.         if (c < ob.min_n) \
  511.             ob.min_n = c; \
  512.         if (c > ob.max_n) \
  513.             ob.max_n = c; \
  514.         wrotethisrow = 0; \
  515.     } \
  516. }
  517.  
  518.     /*
  519.      * Initialise state variables: m = min_m, n = max_n,
  520.      * paint_switch = white.
  521.      */
  522.     m = 0;            /* gb.min_m - gb.min_m */
  523.     n = -gb.max_n;        /* reflected */
  524.     colp = &virtrast[n * stride];
  525. if (colp != buildraster)
  526. panic("gffont drawchar colp != buildraster");
  527.     black = 0;
  528.  
  529.     /*
  530.      * Now interpret the character.
  531.      * `for (;;)' pushes everything off the right edge, alas.
  532.      */
  533. more:
  534.     c = pgetbyte(p);
  535.     if (GF_IsPaint(c))    /* faster? */
  536.         goto paint;
  537.     switch (GF_OpLen(c)) {
  538.  
  539.     case GPL_NONE:
  540.         break;
  541.  
  542.     case GPL_UNS1:
  543.         i = pgetbyte(p);
  544.         break;
  545.  
  546.     case GPL_UNS2:
  547.         pGetWord(p, i);
  548.         break;
  549.  
  550.     case GPL_UNS3:
  551.         pGet3Byte(p, i);
  552.         break;
  553.  
  554.     case GPL_SGN4:
  555.         pGetLong(p, i);
  556.         break;
  557.  
  558.     default:
  559.         panic("gffont drawchar GF_OpLen(%d) = %d", c, GF_OpLen(c));
  560.         /* NOTREACHED */
  561.     }
  562.  
  563.     switch (GF_TYPE(c)) {
  564.  
  565.     case GT_PAINT0:
  566. paint:
  567.         i = c - GF_PAINT_0;
  568.         /* FALLTHROUGH */
  569.  
  570.     case GT_PAINT:
  571.         /*
  572.          * Paint `i' bits in the current row at columns [m..m+i).
  573.          */
  574.         if (i && black) {
  575.             /* remember to adjust n bounds later */
  576.             wrotethisrow = 1;
  577.             /* adjust minimum m bound */
  578.             if (m < ob.min_m)
  579.                 ob.min_m = m;
  580.  
  581.             /*
  582.              * Finish the partial byte at colp.  There are 8-k
  583.              * bits to set to finish it, where k is the bit
  584.              * index value from m.  If we need to set fewer
  585.              * than 8-k bits, set them now and skip the rest
  586.              * of this.
  587.              */
  588.             c = 8 - btobi(m);
  589.             if (i < c) {    /* cannot finish it off */
  590.                 *colp |= UnSign8(lbits[i]) >> btobi(m);
  591.                 m += i;
  592.             } else {    /* finish it off */
  593.                 *colp++ |= rbits[btobi(m)];
  594.                 i -= c;
  595.                 m += c;
  596.  
  597.                 /*
  598.                  * Update m to reflect having written the
  599.                  * remaining i bits, then write them.
  600.                  * First write all the full bytes, then
  601.                  * start a partial byte with whatever
  602.                  * is left over, if anything.
  603.                  */
  604.                 m += i;
  605.                 i >>= 3;
  606.                 while (--i >= 0)
  607.                     *colp++ = 0xff;
  608.                 *colp |= lbits[btobi(m)];
  609.             }
  610.  
  611.             /* adjust maximum m bound */
  612.             if (m > ob.max_m)
  613.                 ob.max_m = m;
  614.         } else {
  615.             /*
  616.              * Add the bit index so that we round up whenever
  617.              * this fills the partial byte at colp.
  618.              */
  619.             colp += (i + btobi(m)) >> 3;
  620.             m += i;
  621.         }
  622.         black = !black;
  623.         break;
  624.  
  625.     case GT_EOC:        /* all done */
  626.         FIX_N_BOUNDS();
  627.         goto done;
  628.  
  629.     case GT_SKIP0:        /* skip no rows */
  630.         i = 0;
  631.         /* FALLTHROUGH */
  632.  
  633.     case GT_SKIP:        /* skip some rows, draw white */
  634.         m = 0;
  635.         black = 0;
  636.         goto skip_or_new_row;
  637.  
  638.     case GT_NEW_ROW:    /* next row near left col, draw black */
  639.         m = c - GF_NEW_ROW_0;
  640.         black = 1;
  641.         i = 0;            /* n offset is 1: skip no rows */
  642. skip_or_new_row:
  643.         FIX_N_BOUNDS();
  644.         n += i + 1;        /* += because reflected */
  645.         colp = &virtrast[n * stride + btoby(m)];
  646.         break;
  647.  
  648.     case GT_XXX:        /* special */
  649.         p += i;
  650.         break;
  651.  
  652.     case GT_YYY:        /* numspecial */
  653.         break;
  654.  
  655.     case GT_NOP:        /* dull */
  656.         break;
  657.  
  658.     case GT_BOC:        /* should not appear */
  659.     case GT_BOC1:
  660.     case GT_CHAR_LOC:
  661.     case GT_CHAR_LOC0:
  662.     case GT_PRE:
  663.     case GT_POST:
  664.     case GT_POSTPOST:
  665.     case GT_UNDEF:
  666.         error(0, 0, "unexpected GF opcode %d", c);
  667.         error(1, 0, "bad GF file \"%s\"", gfname);
  668.         /* NOTREACHED */
  669.  
  670.     default:
  671.         panic("gffont drawchar GF_TYPE(%d) = %d", c, GF_TYPE(c));
  672.         /* NOTREACHED */
  673.     }
  674.     goto more;
  675.  
  676. done:
  677.     /*
  678.      * The observed bounds `m' values are both off by gb.min_m, so
  679.      * fix them now.
  680.      */
  681.     ob.min_m += gb.min_m;
  682.     ob.max_m += gb.min_m;
  683.  
  684.     /* as noted above, we have to make sure there were some points */
  685.     if (ob.min_m > ob.max_m)
  686.         return (nullraster);
  687. if (ob.min_n > ob.max_n)
  688. panic("gffont min>max: n but not m");
  689.  
  690.     /*
  691.      * If we used too much memory for the raster, copy it now.
  692.      */
  693.     if (mustcopy || tempb.min_n != ob.min_n || tempb.max_n != ob.max_n ||
  694.         btonb(ob.max_m - ob.min_m + 1) != stride)
  695.         return (copyit());
  696.  
  697.     /*
  698.      * If the left column bounds match, just move the raster in place.
  699.      */
  700.     if (tempb.min_m == ob.min_m) {
  701.         p = buildraster;
  702.         buildraster = NULL;
  703.         buildsize = 0;
  704.         return (p);
  705.     }
  706.  
  707.     /*
  708.      * The raster must be copied, but only because it is not
  709.      * `left justified'.
  710.      *
  711.      * CONSIDER DEFERRING THIS PHASE UNTIL THE RASTER IS USED
  712.      */
  713.     return (copyit());
  714. }
  715.  
  716. /*
  717.  * Copy the built raster to newly allocated space.
  718.  * We may need to shift all the bits left as well.
  719.  */
  720. char *
  721. copyit()
  722. {
  723.     register char *o, *p;
  724.     register int i, oldoff, newoff;
  725.     char *n;
  726.  
  727.     /*
  728.      * Compute the observed minimum stride.
  729.      */
  730.     newoff = btonb(ob.max_m - ob.min_m + 1);
  731.     n = malloc((unsigned)(newoff * (ob.max_n - ob.min_n + 1)));
  732.     if ((p = n) == NULL)
  733.         return (NULL);
  734.  
  735.     /*
  736.      * Compute the old stride.
  737.      */
  738.     oldoff = btonb(tempb.max_m - tempb.min_m + 1);
  739. if (oldoff < newoff)
  740. panic("gffont copyit oldoff < newoff");
  741.  
  742.     /*
  743.      * Point at the old raster, then add the offset to the first
  744.      * written row, and then the offset to the first written column.
  745.      */
  746.     o = buildraster;
  747.     o += (ob.max_n - tempb.max_n) * oldoff;
  748.     i = ob.min_m - tempb.min_m;
  749.     o += btoby(i);
  750.  
  751.     /*
  752.      * Now copy each row, doing shifting if required.
  753.      */
  754.     if ((i = btobi(i)) != 0) {    /* must shift, alas */
  755.         register int r = 8 - i, j, k;
  756.  
  757.         oldoff -= newoff;
  758.         for (k = ob.max_n; k >= ob.min_n; k--) {
  759.             for (j = newoff; --j > 0;) {
  760.                 *p = *o++ << i;
  761.                 *p++ |= UnSign8(*o) >> r;
  762.             }
  763.             /* last byte is special: no rightward bits */
  764.             *p++ = *o++ << i;
  765.             o += oldoff;
  766.         }
  767.     } else if (oldoff > newoff) {    /* compressing columns */
  768.         for (i = ob.max_n; i >= ob.min_n; i--) {
  769.             bcopy(o, p, newoff);
  770.             o += oldoff;
  771.             p += newoff;
  772.         }
  773.     } else                /* just squeezing out extra rows */
  774.         bcopy(o, p, newoff * (ob.max_n - ob.min_n + 1));
  775.  
  776.     /* finally, return the copy */
  777.     return (n);
  778. }
  779.  
  780. /*
  781.  * Obtain the specified range of glyphs.
  782.  */
  783. static int
  784. gf_getgly(f, l, h)
  785.     register struct font *f;
  786.     int l, h;
  787. {
  788.     register struct glyph *g;
  789.     register struct char_loc *cl;
  790.     register char *p;
  791.     register i32 c;
  792.     register int i;
  793.     register i32 thisboc;
  794.     int abbrev;
  795.     struct gf_details *gd = ftogd(f);
  796.  
  797.     /*
  798.      * For each glyph, make sure there exists an instance of that
  799.      * character residue.  Go find the actual glyph (which may be
  800.      * arbitrarily far down a chain of pointers) and get its info.
  801.      */
  802.     for (cl = &gd->gd_cl[i = l]; i < h; i++, cl++) {
  803.         g = f->f_gly[i];
  804.         thisboc = cl->cl_p;
  805.  
  806.         /*
  807.          * Screw around locating the character for real.
  808.          */
  809.         while (thisboc != -1) {
  810.             p = gd->gd_base + thisboc;
  811. skip:
  812.             c = pgetbyte(p);
  813.             switch (GF_TYPE(c)) {
  814.  
  815.             case GT_XXX:
  816.                 switch (GF_OpLen(c)) {
  817.  
  818.                 case GPL_UNS1:
  819.                     c = pgetbyte(p);
  820.                     break;
  821.  
  822.                 case GPL_UNS2:
  823.                     pGetWord(p, c);
  824.                     break;
  825.  
  826.                 case GPL_UNS3:
  827.                     pGet3Byte(p, c);
  828.                     break;
  829.  
  830.                 case GPL_SGN4:
  831.                     pGetLong(p, c);
  832.                     break;
  833.  
  834.                 default:
  835.                     panic("gf_getgly GF_OpLen(%d) = %d",
  836.                         c, GF_OpLen(c));
  837.                     /* NOTREACHED */
  838.                 }
  839.                 p += c;
  840.                 goto skip;
  841.  
  842.             case GT_YYY:
  843.                 p += 4;
  844.                 goto skip;
  845.  
  846.             case GT_BOC:
  847.                 abbrev = 0;
  848.                 pGetLong(p, c);
  849.                 break;
  850.  
  851.             case GT_BOC1:
  852.                 abbrev = 1;
  853.                 c = pgetbyte(p);
  854.                 break;
  855.  
  856.             default:
  857.                 error(0, 0, "GF code %d; I expected BOC", c);
  858.                 error(1, 0, "bad GF file \"%s\"", f->f_path);
  859.                 /* NOTREACHED */
  860.             }
  861.             /*
  862.              * Found a BOC.  If it is the right character,
  863.              * go handle it.
  864.              */
  865.             if (c == i)
  866.                 goto handleit;
  867.             if ((c & 255) != i) {
  868.                 error(0, 0, "%d != %d mod 256", c, i);
  869.                 error(1, 0, "Bad GF file \"%s\"", f->f_path);
  870.             }
  871.             /*
  872.              * Follow the backpointer.
  873.              */
  874.             if (abbrev)
  875.                 thisboc = -1;
  876.             else
  877.                 pGetLong(p, thisboc);
  878.         }
  879.  
  880.         /*
  881.          * If we get here, the glyph is not valid after all.
  882.          */
  883.         continue;
  884.     
  885.         /*
  886.          * The glyph is okay.  Set it up.
  887.          */
  888. handleit:
  889.         g->g_flags = GF_VALID;
  890.         g->g_xescapement = cl->cl_dx;
  891.         g->g_yescapement = cl->cl_dy;
  892.         g->g_rawtfmwidth = cl->cl_w;
  893.         if (!abbrev)
  894.             p += 4;        /* skip backpointer */
  895.         if ((p = drawchar(p, abbrev, gd->gd_gb, f->f_path)) == NULL)
  896.             return (-1);    /* ??? */
  897.         if (p == nullraster) {
  898.             /* min > max, hence max-min+1 <= 0; we want 0 */
  899.             g->g_height = 0;
  900.             g->g_width = 0;
  901.             g->g_yorigin = 0;
  902.             g->g_xorigin = 0;
  903.             g->g_raster = NULL;
  904.         } else {
  905.             /* set height &c based on observed bounds */
  906.             g->g_height = ob.max_n - ob.min_n + 1;
  907.             g->g_width = ob.max_m - ob.min_m + 1;
  908.             g->g_yorigin = ob.max_n;
  909.             g->g_xorigin = -ob.min_m;
  910.             g->g_raster = p;
  911.         }
  912.         g->g_rotation = ROT_NORM;
  913.     }
  914.     return (0);
  915. }
  916.  
  917. /*
  918.  * Obtain rasters for the specified glyphs.  We did this above, while
  919.  * adjusting the bounding boxes, so this routine should never get called.
  920.  */
  921. static int
  922. gf_rasterise(f, l, h)
  923.     struct font *f;
  924.     int l, h;
  925. {
  926.  
  927.     panic("gf_rasterise(%s, %d, %d)", f->f_path, l, h);
  928. }
  929.  
  930. /*
  931.  * Discard the font details.
  932.  */
  933. static void
  934. gf_freefont(f)
  935.     struct font *f;
  936. {
  937.     struct gf_details *gd;
  938.  
  939.     if ((gd = ftogd(f)) != NULL) {
  940.         free(gd->gd_body);
  941.         free((char *) gd);
  942.     }
  943. }
  944.